home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 2: Applications
/
Linux Cubed Series 2 - Applications.iso
/
math
/
gle-3.000
/
gle-3
/
gle
/
bmp.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-02-07
|
35KB
|
1,211 lines
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#include <math.h>
#include "int32.h"
#ifdef __TURBOC__
#include <mem.h>
#include <alloc.h>
#else
#define farcalloc calloc
#define farcoreleft() (1200000)
#endif
#ifdef unix
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#endif
#if (defined DJ || defined EMXOS2 ) /* a.r. */
#define EXIT_FAILURE 1
#endif
#include "bmp.h"
#define CLIPSIZE ((int32) PWIDTH* (int32) sizeof(int)* (int32) (b->ny+2))
#define dbg if (gdebug==true)
#define false 0
#define true !0
extern int gdebug;
int iscolor;
extern int dev_noclip;
int row_show(char *s,Run *r,int y);
int row_init(Run *r, int ny);
int bmp_paintsort(int *p, int np);
int row_free(Run *r, int ny);
int row_grow(Run *r, int y, int v);
int bmp_ink4(Bitmap *bb,unsigned int savem,int cindex);
int bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex);
int bmpcheck(Bitmap *b);
/*
Filling routines to allow an arbitrary dimensioned
bitmap to be drawn into.
*/
/* General notes:
Color and pattern are the same thing, on a
color system the pattern array would have the
same depth as the bitmap itself.
White bit = 1;
Black bit = 0;
*/
/* allocates the storage required.
initializes it
returns NULL if not enough memory
returns pointer to Bitmap structure
(ignoring depth at the moment)
*/
/* FILE *fgle; */
Bitmap *bmp_open(int xsize,int ysize,int depth, int bmp_compress)
{
Bitmap *b;
int *p;
int i,j;
/* fgle = fopen("test.gle","w");
fprintf(fgle,"size 15 15\n");
fprintf(fgle,"scale .3 .3 \n");
*/
b = (Bitmap *) calloc(1,sizeof(Bitmap));
if (b==NULL) bmp_die("No memory for Bitmap structure\n");
b->nx = xsize;
b->ny = ysize;
b->compress = bmp_compress;
row_init(&b->clip,b->ny);
row_init(&b->paint,b->ny);
row_init(&b->horiz,b->ny);
b->data = (char *(*)[]) calloc(1,sizeof(int *) * (ysize+3));
if (b->data == NULL) bmp_die("No memory for bitmap pointers \n");
{ int32 x;
if (iscolor) x=xsize/2;
else x=xsize/8;
x = x*ysize+80000L;
if (farcoreleft() < x) b->compress = true;
}
if (b->compress) printf("Compressing internal bitmap to save memory\n");
if (b->compress==false) {
for (i=0; i<=ysize+1; i++) {
if (iscolor) {
if ( ((*b->data)[i] = calloc(1,xsize/2+2)) == NULL)
bmp_die("No memory for bitmap\n");
memset( (*b->data)[i], 255, xsize/2+2);
} else {
if ( ((*b->data)[i] = calloc(1,xsize/8+2)) == NULL)
bmp_die("No memory for bitmap\n");
memset( (*b->data)[i], 255, xsize/8+2);
}
}
}
b->painty1 = ysize;
b->lwidth = 1;
b->lstyle = 0x8000001e;
b->lstyle_mask = 0x80000000;
b->lstyle_dotlen = 1;
b->lstyle_dotpix = 0;
bmp_color(b,0);
#ifdef __TURBOC__
/* printf("Free memory after bitmap allocated %ld \n",farcoreleft()); */
#endif
return b;
}
row_init(Run *r, int ny)
{
r->alloc = (unsigned char *) calloc(1,ny+3);
if (r->alloc == NULL) bmp_die("Not enough memory for run counts \n");
r->used = (unsigned char *) calloc(1,ny+3);
if (r->used == NULL) bmp_die("Not enough memory for run counts \n");
r->row = (typrow) calloc(sizeof(int *),ny+3);
if (r->row == NULL) bmp_die("Not enough memory for run counts \n");
}
row_free(Run *r, int ny)
{
int i,*rr;
for (i=0;i<=ny;i++) {
rr = (*r->row)[i];
if (rr!=NULL) free(rr);
}
free(r->row);
free(r->used);
free(r->alloc);
}
int row_shrinkx(Run *r, int ny);
int row_shrink(Bitmap *b);
row_shrink(Bitmap *b)
{
row_shrinkx(&b->paint,b->ny);
row_shrinkx(&b->horiz,b->ny);
}
row_shrinkx(Run *r, int ny)
{
int i,*rr;
for (i=0;i<=ny;i++) {
rr = (*r->row)[i];
if (rr!=NULL) free(rr);
(*r->row)[i] = NULL;
r->used[i] = 0;
r->alloc[i] = 0;
}
}
#define row_data(r,y) ( (*r.row)[y] )
#define row_used(r,y) ( r.used[y] )
#define row_setused(r,y,v) ( r.used[y] = v )
row_grow(Run *r, int y, int v)
{
int vv;
int *z;
v += r->used[y];
if (v<= r->alloc[y]) {
r->used[y] = v;
return;
}
vv = v;
if ((v&1)==1) vv++;
z = (*r->row)[y] ;
if (z==NULL) z = (int *) malloc(vv*sizeof(int));
else z = (int *) realloc((*r->row)[y],vv*sizeof(int));
/*
if (z==NULL) z = malloc(vv*sizeof(int));
else {
z = malloc(vv*sizeof(int));
memcpy(z, (*r->row)[y] ,r->used[y]*sizeof(int));
free( (*r->row)[y] );
}
*/
(*r->row)[y] = z;
/* malloc(v); */
if ((*r->row)[y] == NULL) bmp_die("Could not grow row count data \n");
r->alloc[y] = vv;
r->used[y] = v;
}
/* frees up all storage. */
iffree(void *block)
{
if (block!=NULL) free(block);
}
bmp_close(Bitmap *b)
{
int i,j;
if (b==NULL) return;
for (i=0; i<=b->ny+2; i++) {
iffree((*b->data)[i]);
}
row_free(&b->paint,b->ny);
row_free(&b->clip,b->ny);
row_free(&b->horiz,b->ny);
/* fclose(fgle); */
}
/*
Draws line of current lwidth, lstyle,
and color/pattern
Line is clipped using clip array.
*/
#define sign(x) ((x) > 0 ? 1: ((x) == 0 ? 0: (-1)))
bmp_line(Bitmap *b,int x1,int y1,int x2,int y2)
{
int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
register int x,y;
uint32 mask,pattern,lastpatbit;
int lwidth, dotlen,pix;
lwidth = b->lwidth/2;
mask = b->lstyle_mask;
pattern = b->lstyle;
lastpatbit = 1l << (pattern & 0x1f);
dotlen = b->lstyle_dotlen;
pix = b->lstyle_dotpix;
/* printf("lstyle %08lx, mask %08lx, dotlen %d, dotpix %d, lastpatbit %8lx pat= %lx \n",
pattern,mask,dotlen,pix,lastpatbit,pattern & 0x1f);
*/
if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return; /* clip to bitmap */
dx = x2 - x1;
dy = y2 - y1;
sdx = sign(dx);
sdy = sign(dy);
dxabs = abs(dx);
dyabs = abs(dy);
x = 0;
y = 0;
px = x1;
py = y1;
if (dxabs >= dyabs) {
mask = (mask & lastpatbit) ? 0x80000000 : mask;
if (pattern & mask) {
for (j= -lwidth; j<=lwidth; j++)
bmp_pixel(b,px,py+j);
}
if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
for (i=0; i<dxabs; i++) {
mask = (mask & lastpatbit) ? 0x80000000 : mask;
y += dyabs;
if (y>=dxabs) {
y -= dxabs;
py += sdy;
}
px += sdx;
if (pattern & mask) {
for (j= -lwidth; j<=lwidth; j++)
bmp_pixel(b,px,py+j);
}
if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
}
} else {
mask = (mask & lastpatbit) ? 0x80000000 : mask;
if (pattern & mask) {
for (j= -lwidth; j<=lwidth; j++)
bmp_pixel(b,px+j,py);
}
if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
for (i=0; i<dyabs; i++) {
mask = (mask & lastpatbit) ? 0x80000000 : mask;
x += dxabs;
if (x>=dyabs) {
x -= dyabs;
px += sdx;
}
py += sdy;
if (pattern & mask) {
for (j= -lwidth; j<=lwidth; j++)
bmp_pixel(b,px+j,py);
}
if ((++pix) >= dotlen) {mask >>= 1; pix=0;}
}
}
b->lstyle_mask = mask;
b->lstyle_dotpix = pix;
/* printf("lstyle %08x, mask %08x, lastpatbix %08x, dotpix %d \n",
pattern, mask, lastpatbit, pix); */
}
/*
Apply clipping
Get bit from ink
Get row of bitmap
Place bit into row
*/
static Bitmap *pr_lb;
static int pr_ly;
static char *pr_row;
bmp_pixel(register Bitmap *b,register int x,register int y)
{
static int i,spot;
int ry;
/* static char *row; */
unsigned char *k;
if (b->clipping) if (bmp_invis(b,x,y)) return;
if (x> b->nx || x<0 || y>b->ny || y<0) return;
ry = y % 16;
if (pr_ly!=y || pr_lb!=b) {
pr_row = bmp_row(b,y);
pr_ly = y; pr_lb = b;
}
k = (unsigned char *) &b->ink[ry%16][0];
spot = k[x%16];
if (iscolor) {
i = pr_row[x/2];
if (x % 2==0) {
i = (i & 0x0f) | (spot << 4);
} else {
i = (i & 0xf0) | spot;
}
pr_row[x/2] = i;
return;
}
if (k[x % 16] != 0) { /* a white spot */
*(pr_row + x/8) |= (1 << (x%8));
} else {
*(pr_row + x/8) &= (255-(1 << (x%8)));
}
}
bmp_paintrange(Bitmap *b,int y, register int x1, int x2)
{
static int i,spot;
int ry;
/* static char *p;*/
unsigned char *k;
/* debugging stuff */
if (x1==-2 || x2==-2) {
printf("********Stuffed range on line %d, %d-->%d \n",y,x1,x2);
return;
}
dbg printf("Paint range %d, %d %d \n",y,x1,x2);
/* end debug */
/* printf("Paint range %d, %d %d \n",y,x1,x2);*/
ry = y % 16;
if (pr_ly!=y || pr_lb!=b) {
pr_row = bmp_row(b,y);
pr_ly = y; pr_lb = b;
}
k = (unsigned char *) &b->ink[ry%16][0];
if (iscolor) {
for (;x1<=x2;x1++) {
spot = k[x1%16];
i = pr_row[x1/2];
if (x1 % 2==0) {
i = (i & 0x0f) | (spot << 4);
} else {
i = (i & 0xf0) | spot;
}
pr_row[x1/2] = i;
}
return;
}
for (;x1<=x2;x1++) {
if (k[x1 % 16] != 0) { /* a white spot */
*(pr_row + x1/8) |= (1 << (x1%8));
} else {
*(pr_row + x1/8) &= (255-(1 << (x1%8)));
}
}
}
/* return true if pixel at that
location is clipped
*/
int bmp_invis(Bitmap *b, int x, int y)
{
int *c,nc,i;
if (! b->clipping) return false; /* clipping os off */
c = row_data(b->clip,y);
if (*c==0) return true; /* clipping */
nc = row_used(b->clip,y);
for (i=0;i<nc-1;i+=2, c+=2) {
if ( (x>= *c) && (x<= *(c+1))) return false; /* is visible */
}
return true;
}
/*
Adds x values at y crossings onto the paint[] array.
Doesn't add last crossing
Sets maxy,miny
Special cases:
move
init lddy
sx,sy, x1,y1 ...
* Change in sdy
put in double x value
* When end of line meets start of line.
remember start of line with bmp_pmove
remember start sdy
if sdy == enddy then don't put endx,endy
start new polygon.
(at fill check lines is closed, if not then close before fill)
* (WRONG) Start of Horizontal lines
put in start xvalue, (if not first line in path)
* Continued horizontal line
do nothing
* (WRONG) end of horizontal line
Put in last x(thisy) value
* with horizontal lines or lines which have multiple x values
store the range of values into b->horiz[][] so they can
also be drawn in. This gets the middle of an H or A or top
of a B drawn correctly if the bar is very thin.
*/
bmp_pmove(Bitmap *b,int x1,int y1)
{
bmp_clipline(b,&x1,&y1,&x1,&y1); /* clip to bitmap */
/* fprintf(fgle,"amove %d %d \n",x1,y1); */
if (b->sx != b->x1 || b->sy != b->y1) {
printf("Closing path\n");
bmp_pline(b,b->sx,b->sy);
}
/* printf("pmove %d %d \n",x1,y1); */
b->sx = x1; b->sy = y1;
b->x1 = x1; b->y1 = y1;
b->sddy = -2;
b->lddy = -2;
}
bmp_pline(Bitmap *b,int x2,int y2)
{
int dx, dy, dxabs, dyabs, i, j, px, py, sdx, sdy;
int endy,xwid;
register int x,y;
int x1=b->x1, y1=b->y1; /* start of line */
int lddy=b->lddy;
int ddy,horizx;
if (x1==x2 && y1==y2) return; /* not going anywhere */
if (bmp_clipline(b,&x1,&y1,&x2,&y2)) return; /* clip to bitmap */
/* fprintf(fgle,"aline %d %d \n",x2,y2);
printf("CVector %d,%d --- %d,%d \n",x1,y1,x2,y2);
*/
b->x1 = x2; b->y1 = y2; /* remember end of line */
bmp_minmax(b,y1);
bmp_minmax(b,y2); /* remember range of y paint values */
dx = x2 - x1;
dy = y2 - y1;
xwid = dx/2;
sdx = sign(dx);
sdy = sign(dy);
dxabs = abs(dx);
dyabs = abs(dy);
x = 0;
y = 0;
px = x1;
py = y1;
endy = y2;
ddy = sdy;
if (dy==0) ddy = 0; /* ddy = -1, 0, 1 */
if (ddy==0) { /* this is a horizontal line */
bmp_painth(b,x1,x2,y1); /* paint the whole line */
goto endpline;
}
if (lddy == -ddy) bmp_paintx(b,x1,y1); /* put in last endxy */
if (dxabs >= dyabs) {
horizx = px+sdx; /* start of first row */
for (i=0; i<dxabs; i++) {
y += dyabs;
if (y>=dxabs) {
y -= dxabs;
bmp_painth(b,horizx,px,py); /* end of that row */
py += sdy;
horizx = px+sdx; /* start of next row */
/* if (py==endy) break; */
bmp_paintx(b,px+sdx,py);
}
px += sdx;
}
} else {
for (i=0; i<dyabs; i++) {
x += dxabs;
if (x>=dyabs) {
x -= dyabs;
px += sdx;
}
py += sdy;
bmp_paintx(b,px,py);
}
}
endpline:
if (ddy!=0) { /* remember last line if not horiz */
b->lddy = ddy;
if (lddy== -2) { /* first line */
b->sddy = ddy;
b->ssx = x1;
b->ssy = y1;
return;
}
}
if (x2==b->sx && y2==b->sy) { /* path is closed */
if (b->sddy == -b->lddy) { /* direction changed */
bmp_paintx(b,b->ssx,b->ssy);
}
}
}
bmp_minmax(Bitmap *b,int y) /* remember range of y paint values */
{
if (y<b->painty1) b->painty1 = y;
if (y>b->painty2) b->painty2 = y;
}
/*
Adds x value onto paint[] range table
*/
bmpcheck(Bitmap *b)
{
int i,*p;
for (i=0;i<16;i++) {
/* p = &(*b->paint)[i][0];
printf("P[%d] = %d %d %d %d \n",i,*p,*(p+1),*(p+2),*(p+3));
*/
}
}
bmp_paintx(Bitmap *b, int x, int y)
{
int *c,nc,i,nrow;
i = 0;
row_grow(&b->paint,y,1);
c = row_data(b->paint,y);
c += row_used(b->paint,y) - 1;
*c = x;
c = row_data(b->paint,y);
nc = row_used(b->paint,y);
/*
printf("Paint [%d] x=%d , ",y,x);
for (i=0;i<nc;i++,c++) {
printf("%d ",*c);
}
printf("\n");
*/
}
row_show(char *s,Run *r,int y)
{
int i,*c,nc;
c = (*r->row)[y];
nc = r->used[y];
printf("show {%s} [%d] ",s,y);
for (i=0;i<nc;i++,c++) {
printf("%d ",*c);
}
printf("\n");
}
/*
This routine remembers the horizontal lines that
need to be drawn.
They don't need sorting, and they can be amalgamated e.g.
They do need putting into ascending order when used.
1 7, 5 9, can become 1 9
*/
showhy(Bitmap *b, int y)
{
int *c,i;
i = 0;
/* c = &(*b->horiz)[y][0];
c = (*b->horiz.row)[y];
printf("showy ");
for (;i < (*b->horiz.used)[y];c+=2 ,i+=2) {
printf("%d %d ",*c,*(c+1));
}
printf("\n");
*/
}
bmp_painth(Bitmap *b, int x1,int x2, int y)
{
int *c,i,nc;
/* printf("Addh, (%d) %d %d \n",y,x1,x2); */
if (x1>x2) {i=x2; x2=x1; x1=i;}
i = 0;
c = row_data(b->horiz,y);
nc = row_used(b->horiz,y);
for (;i < nc-1 ;c+=2 ,i+=2) {
if (*c<=x1 && *(c+1)>=x1) {
c++;
if (*c < x2) *c = x2;
return;
}
if (*c<=x2 && *(c+1)>=x2) {
if (*c > x1) *c = x1;
return;
}
if (*c-1 == x2) { *c = x1; return;}
if (*(c+1)+1 == x1) { *(c+1) = x2; return;}
}
/* found an empty slot */
row_grow(&b->horiz,y,2); /* make it two bigger */
c = row_data(b->horiz,y);
nc = row_used(b->horiz,y);
c += nc - 2;
*c = x1;
*(c+1) = x2;
}
/* Clear the current path. */
bmp_newpath(Bitmap *b)
{
int i,j;
int *c;
for (i=b->painty1; i<=b->painty2; i++) {
row_setused(b->paint,i,0);
row_setused(b->horiz,i,0);
}
b->painty1 = b->ny+2;
b->painty2 = 0;
if (farcoreleft()<50000L) row_shrink(b);
}
/*
from painty1 to painty2
sort x's and call bmp_paint(b,y,x1,x2);
*/
bmp_paintsort(int *p, int np)
{
int *pp = p;
int a,b,fixed,i;
fixed = true;
for (;fixed;) {
fixed = false;
for (p = pp, i = 0; i<(np-1); i++, p++) {
if (*p > *(p+1)) {
a = *p;
*p = *(p+1);
*(p+1) = a;
fixed=true;
}
}
}
p = pp;
/*
printf("(sort) ");
for (;*p!=-2;p++) printf("%d ",*p);
printf("\n");
*/}
bmp_fill(Bitmap *b)
{
int i,k,nrow,ncrow,j,x1,x2;
int *c,*p,np,nc;
/* printf ("Fill, color is %d \n",b->ink[0][0]); */
if (b->sx != b->x1 || b->sy != b->y1) {
printf("Closing path\n");
bmp_pline(b,b->sx,b->sy);
}
for (i=b->painty1; i<=b->painty2; i++) {
p = row_data(b->paint,i);
np = row_used(b->paint,i);
bmp_paintsort(p,np);
for (j=0;j<np-1; j+=2, p+=2) {
c = row_data(b->clip,i);
nc = row_used(b->clip,i);
if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
else {
for (k=0;k<nc-1; k+=2, c+=2) {
x1 = *p; x2 = *(p+1);
if (x1< *c) x1 = *c;
if (x2> *(c+1)) x2 = *(c+1);
if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
}
}
}
/* now paint the thin horizontal bits */
p = row_data(b->horiz,i);
np = row_used(b->horiz,i);
for (j=0;j<np-1; j+=2, p+=2) {
if (!b->clipping) bmp_paintrange(b,i,*p,*(p+1)); /* no clipping */
else {
c = row_data(b->clip,i);
nc = row_used(b->clip,i);
for (k=0;k<nc-1; k+=2, c+=2) {
x1 = *p; x2 = *(p+1);
if (x1< *c) x1 = *c;
if (x2> *(c+1)) x2 = *(c+1);
if (x1<=x2) bmp_paintrange(b,i,x1,x2); /* clipped range */
}
}
}
/* end horizontal bits */
}
}
/* Coppies bitmap on while applying clip (not using ink[])
*/
/*
bmp_copy(Bitmap *b,char *bitmap,int nx,int ny)
{
}
*/
/* Move paint array onto clip array. */
bmp_clip(Bitmap *b)
{
int i;
int *c,*p,nc;
if (dev_noclip) return;
/* Sort the paint array before copying it */
for (i=0;i<b->ny; i++) {
c = row_data(b->paint,i);
bmp_paintsort(c,row_used(b->paint,i));
}
/* Now simply copy it over */
for (i=0;i<b->ny; i++) {
p = row_data(b->paint,i);
nc = row_used(b->paint,i);
if (nc>0) {
row_grow(&b->clip,i,nc);
c = row_data(b->clip,i);
memcpy(c,p,nc*sizeof(int));
}
}
b->clipping = true; /* remeber that clipping is on now */
}
/* Clears the clipping array */
bmp_newclip(Bitmap *b)
{
int i,j;
int *c;
if (dev_noclip) return;
b->clipping = false;
for (i=0; i<=b->ny+1; i++) {
row_setused(b->clip,i,0);
}
}
/*
Coppies clipping array and lastclip pointer into malloced area
and sets lastclip to point to this new malloced area.
*/
bmp_saveclip(Bitmap *b)
{
int *c;
if (dev_noclip) return;
/* should save clipping region */
}
bmp_restoreclip(Bitmap *b)
{
int *c;
if (dev_noclip) return;
/* should restore from saved memory but I'm in a hurry */
b->clipping = false;
#ifdef __TURBOC__
row_shrinkx(&b->clip,b->ny);
#endif
}
/* Sets ink based on a lookup table
255 = white, 0 = black
*/
bmp_color(Bitmap *b,int colindex)
{
int i,j;
for (i=0;i<16;i++)
for (j=0;j<16;j++)
b->ink[i][j] = colindex;
}
unsigned int grey_bits[] = {0x0000, 0x0200, 0x0802, 0x0a02,
0x5050, 0x5250, 0x5852, 0x5a52,
0xa5a5, 0xa7a5, 0xada7, 0xafa7,
0xf5f5, 0xf7f5, 0xfdf7, 0xfff7, 0xffff};
static unsigned int pat_shade1[] = {
0xc000, 0x6000, 0x3000, 0x1800, 0xc00, 0x600, 0x300,
0x180, 0xc0, 0x60, 0x30, 0x18, 0xc, 0x6, 0x3, 0x8001 };
static unsigned int pat_shade2[] = {
0xc018, 0x600c, 0x3006, 0x1803, 0x8c01, 0xc600, 0x6300, 0x3180,
0x18c0, 0xc60, 0x630, 0x318, 0x18c, 0xc6, 0x63, 0x8031 };
static unsigned int pat_shade3[] = {
0xf078, 0x783c, 0x3c1e, 0x1e0f, 0x8f07, 0xc783, 0xe3c1, 0xf1e0,
0x78f0, 0x3c78, 0x1e3c, 0xf1e, 0x78f, 0x83c7, 0xc1e3, 0xe0f1 };
static unsigned int pat_shade4[] = {
0x7e00, 0x3f00, 0x1f80, 0xfc0, 0x7e0, 0x3f0, 0x1f8, 0xfc,
0x7e, 0x3f, 0x801f, 0xc00f, 0xe007, 0xf003, 0xf801, 0xfc00 };
static unsigned int pat_shade5[] = {
0x6006, 0x7ffe,0x6006,0x300c,0x1818,0xc30, 0x660, 0x3c0,
0x660, 0xc30, 0x1998,0x33cc,0x67e6,0x7ffe,0x6006, 0x6006 };
static unsigned int pat_grid1[] = {
0xc003, 0x6006, 0x300c, 0x1818, 0xc30, 0x660, 0x3c0, 0x180,
0x3c0, 0x660, 0xc30, 0x1818, 0x300c, 0x6006, 0xc003, 0x8001 };
static unsigned int pat_grid2[] = {
0xf00f, 0x781e, 0x3c3c, 0x1e78, 0xff0, 0xfe0, 0xfc0, 0xf80,
0xfc0, 0xfe0, 0xff0, 0x1e78, 0x3c3c, 0x781e, 0xf00f, 0xf00f };
static unsigned int pat_grid3[] = {
0xffff, 0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff,
0xffff, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0x3c3c, 0xffff, 0xffff};
static unsigned int pat_grid4[] = {
0x303, 0x303, 0xcfc0, 0xcfc0, 0x3ff0, 0x3ff0, 0xfcc, 0xfcc,
0x303, 0x303, 0xcc0f, 0xcc0f, 0xf03f, 0xf03f, 0xc0cf, 0xc0cf };
static unsigned int pat_grid5[] = {
0x300, 0x300, 0x300, 0x300, 0xcc0, 0xcc0, 0xf03f, 0xf03f,
0x3, 0x3, 0x3, 0x3, 0xc00c, 0xc00c, 0x3ff0, 0x3ff0 };
#define NGREY 17
bmp_setcolor(Bitmap *bb,int r, int g, int b, int ftyp)
{
/* values between 0-255 */
unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy,savem;
unsigned int *patt;
int cindex;
float f;
f = (r*3+g*2+b)/(255*6.0);
i = (1-f)*(NGREY-.8);
if (f<1 && i==0) i = 1;
savem = grey_bits[i];
/* Fill types,
2=pat_black, 3=pat_red, 4=pat_green,
5=pat_blue, 6=pat_yellow
*/
if (ftyp>1 && ftyp<7) {
cindex = 0;
if (ftyp==3) cindex = 1;
if (ftyp==4) cindex = 2;
if (ftyp==5) cindex = 4;
if (ftyp==6) cindex = 3;
if (!iscolor) cindex = 0;
if (g==0x0 && b==0x20) patt = pat_shade1;
if (g==0x0 && b==0x0c) patt = pat_shade1;
if (g==0x0 && b==0x10) patt = pat_shade2;
if (r==0x5 && b==0x20) patt = pat_shade3;
if (g==0x0 && b==0x40) patt = pat_shade4;
if (g==0x0 && b==0x60) patt = pat_shade5;
if (g==0x20 && b==0x20) patt = pat_grid1;
if (g==0xf && b==0xf) patt = pat_grid1;
if (g==0x10 && b==0x10) patt = pat_grid2;
if (g==0x20 && b==0x20) patt = pat_grid3;
if (g==0x40 && b==0x40) patt = pat_grid4;
if (g==0x60 && b==0x60) patt = pat_grid5;
bmp_ink16(bb,patt,cindex);
return;
}
/* 0 = black, 1=red, green, blue, yellow, magenta, brown, ... white */
if (r==g && g==b) {
bmp_ink4(bb,savem,0);
return;
}
if (iscolor) {
cindex = -1;
if (r>20 && g==0 && b==0) {cindex = 1; f=r;}
if (g>20 && r==0 && b==0) {cindex = 2; f=g;}
if (b>20 && g==0 && r==0) {cindex = 4; f=b;}
if (r>20 && g>20 && b==0) {cindex = 3; f=r;}
if (cindex>=0) {
f = f/255.0;
i = (f)*(NGREY-.8);
if (f<1 && i==(NGREY-1)) i = NGREY-2;
bmp_ink4(bb,grey_bits[i],cindex);
return;
}
if (r>150 && g<50 && b<50) cindex = 1;
if (r<50 && g>150 && b<50) cindex = 2;
if (r<50 && g<50 && b>150) cindex = 4;
if (r>150 && g>150 && b<50) cindex = 3;
if (b>50 && g>50 && r<18) cindex = 6; /* CYAN */
if (r>50 && b>50 && g<20) cindex = 5; /* Magenta */
if (cindex >= 0) {
bmp_color(bb,cindex);
return;
}
}
bmp_ink4(bb,savem,0);
}
bmp_ink4(Bitmap *bb,unsigned int savem,int cindex)
{
/* values between 0-255 */
unsigned int i,j,m,nib,k,n,xx,savenib,ix,iy;
unsigned int *patt;
float f;
for (ix=0; ix<16; ix+=4) {
for (iy=0; iy<16; iy+=4) {
m = savem;
for (j=0; j<4; j++) {
nib = m & 0xf;
for (k=0; k<4; k++) {
if (nib&1) bb->ink[ix+j][iy+k] = cindex;
else bb->ink[ix+j][iy+k] = 15;
nib = nib >> 1;
}
m = m >> 4;
}
}
}
}
bmp_ink16(Bitmap *bb,unsigned int newink[],int cindex)
{
unsigned int m;
int i,ix,iy;
for (iy=0; iy<16; iy++) {
m = newink[iy];
for (ix=15; ix>=0; ix--) {
if (m&1 == 1) bb->ink[iy][ix] = cindex;
else bb->ink[iy][ix] = 15;
/* printf("ix iy %d %d %d\n",ix,iy,bb->ink[ix][iy]);
*/ m = m >> 1;
}
}
}
bmp_lwidth(Bitmap *b,int x)
{
b->lwidth = x;
}
bmp_lstyle(Bitmap *b,int32 n,int l)
/* n is a pattern, 01110001110; l is len of one pattern dot in pixels */
{
b->lstyle = n;
b->lstyle_mask = 0x80000000;
b->lstyle_dotlen = l;
b->lstyle_dotpix = 0;
}
/* (depth must be 1, expands this into the pat[][] array,
each 1 becomes a 255)
*/
/*
bmp_pattern(Bitmap *b,char *pat,int nxbytes,int nybytes,int depth)
{
}
*/
/* Returns pointer to a row of the bitmap */
unsigned char *bmp_expanded(Bitmap *b,int y);
char *bmp_row(Bitmap *b,int y)
{
pr_ly = -1;
if (b->compress) {
return (char *) bmp_expanded(b,y);
} else {
return (*b->data)[y];
}
}
/* this compression routine won't work with more than one 'Bitmap' as
it doesn't store it's data in Bitmap *b, like it should. */
unsigned char *bmp_expanded(Bitmap *b,int y)
{
static unsigned char *bitrow,*bitc;
static unsigned char *o,*bc,c,*lastv;
static int lasty = -2;
char *v;
int nc,x,i,j,nxbyte;
int totwid = 0;
if (lasty==y) return bitrow;
if (y>b->ny+1) goto return_null;
nxbyte = b->nx/8+1;
if (iscolor) nxbyte = b->nx/2+2;
if (bitrow==NULL) bitrow = (ucharp) calloc(1,nxbyte+3);
if (bitc == NULL) bitc = (ucharp) calloc(1,nxbyte*2+3);
if (bitrow==NULL || bitc==NULL) bmp_die("bitc allocation error\n");
v = (*b->data)[y];
if (lasty != -2) {
o = bitc;
/* if (lasty==296) {
printf("Store [%d]",lasty);
for (i=0;i<nxbyte;i++) printf("%x ",bitrow[i]);
printf("\n");
}
*/
for (x=0; x<nxbyte ; x++) {
c = bitrow[x];
nc = 1;
for (;x<(nxbyte-1) && bitrow[x+1]==c && nc<250; x++) nc++;
*o++ = nc;
*o++ = c;
totwid = totwid + 2;
}
if (totwid>nxbyte*2) printf("Total width %d nx=%d\n",totwid,nxbyte);
*o++ = 0;
*o++ = 0; /* nulls at end */
nc = o-bitc+1;
if (lastv!=NULL) lastv = (unsigned char *) realloc(lastv,nc);
else lastv = (ucharp) malloc(nc);
if (lastv==NULL) {
printf("Failed to allocate enough memory for bitmap \n");
abort();
}
memcpy(lastv,bitc,nc);
(*b->data)[lasty] = (char *) lastv;
}
lasty = y;
lastv = (ucharp) v;
nc = 0;
if (v==NULL) {
return_null: memset(bitrow,255,nxbyte);
return bitrow;
}
nc = 0;
bc = (ucharp) v;
for (i=0, o = bitrow; bc[i]!=0 ; i+=2) {
for (j=0; j<bc[i]; j++) {
*o++ = bc[i+1]; nc++;
if (nc>nxbyte) {
printf("ERR[%d] ",y);
for (i=0;bc[i]!=0;i+=2) printf("%d,%x ",bc[i],bc[i+1]);
printf("\n");
printf("gone past end [%d] %d %d \n",y,nxbyte,nc);
return bitrow;
}
}
}
/*
if (y==296) {
printf("EXP[%d] ",y); for (i=0;i<10;i++) printf("%d ",bitrow[i]);
printf("\n");
}
*/
return bitrow;
}
bmp_die(char *s)
{
printf("%s",s);
exit(EXIT_FAILURE);
}
bmp_pbezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
{
float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep;
int dist,i;
dbg printf("pbezier, %d %d %d %d %d %d %d %d \n",x0,y0,x1,y1,x2,y2,x3,y3);
dist = abs(x3-x0) + abs(y3-y0);
nstep = 20;
if (dist<30) nstep = 10;
if (dist<10) nstep = 5;
if (dist<5) nstep = 3;
if (dist<=2) {
bmp_pline(bb,x3,y3);
return;
}
cx = (x1-x0)*3;
bx = (x2-x1)*3-cx;
ax = x3-x0-cx-bx;
cy = (y1-y0)*3;
by = (y2-y1)*3-cy;
ay = y3-y0-cy-by;
for (i=0;i<=nstep;i++) {
t = (float) i/nstep;
xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
bmp_pline(bb,(int) xxx,(int) yyy);
}
}
bmp_bezier(Bitmap *bb,int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3)
{
float ax,bx,cx,ay,by,cy,xxx,yyy,t,nstep,xx,yy;
int dist,i;
dist = abs(x3-x0) + abs(y3-y0);
nstep = 20;
if (dist<30) nstep = 10;
if (dist<10) nstep = 5;
if (dist<5) nstep = 3;
if (dist<=2) {
bmp_line(bb,x0,y0,x3,y3);
return;
}
cx = (x1-x0)*3;
bx = (x2-x1)*3-cx;
ax = x3-x0-cx-bx;
cy = (y1-y0)*3;
by = (y2-y1)*3-cy;
ay = y3-y0-cy-by;
xx = x0; yy = y0;
for (i=0;i<=nstep;i++) {
t = (float) i/nstep;
xxx = ax*pow(t,3.0) + bx*t*t + cx*t + x0;
yyy = ay*pow(t,3.0) + by*t*t + cy*t + y0;
bmp_line(bb,(int) xx,(int) yy, (int) xxx, (int) yyy);
xx = xxx; yy = yyy;
}
}
#define OUTCODES_CSD( X, Y, OUTCODE ) \
( OUTCODE ) = 0; \
if ((Y) >= b->ny ) OUTCODE |= 1; \
else if ((Y) < 0 ) OUTCODE |= 2; \
if ((X) >= b->nx ) OUTCODE |= 4; \
else if ((X) < 0 ) OUTCODE |= 8;
int bmp_clipline(Bitmap *b,int *x1, int *y1, int *x2, int *y2)
{
int outcode1,outcode2;
OUTCODES_CSD( *x2, *y2, outcode2 );
OUTCODES_CSD( *x1, *y1, outcode1 );
if (outcode1 & outcode2) /* trivial reject */
return true; /* throw line away */
if (!(outcode2 | outcode1)) /* trivial accept */
return false;
doclip(0,b->nx-1,x1);
doclip(0,b->nx-1,x2);
doclip(0,b->ny-1,y1);
doclip(0,b->ny-1,y2);
return false;
}
doclip(int min, int max, int *v)
{
if (*v < min) *v = min;
if (*v > max) *v = max;
}
showfree()
{
#ifdef __TURBOC__
struct farheapinfo hi;
int32 total=0;
hi.ptr = NULL;
while( farheapwalk( &hi ) == _HEAPOK ) {
if (!hi.in_use) total += hi.size;
}
printf("Total mem free %ld \n",total);
#endif
}